﻿using Nemerle;
using Nemerle.Collections;
using Nemerle.Extensions;
using Nemerle.Text;
using Nemerle.Utility;

using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Windows.Forms;
using Nemerle2.Compiler;
using Nemerle.Compiler;
using DocBrowser.Config;
using Nemerle.Xml;

namespace DocBrowser
{
  /// <summary>
  /// Description of MainForm.
  /// </summary>
  public partial class MainForm : Form
  {
    _host : Host = Host();
    static TempPath = Path.GetTempFileName();
    
    public this()
    {
      InitializeComponent();
      _metadataTree.Host = _host;
      _metadataTree.SelectedMetadataChanged += metadata => Diagnostics.Trace.WriteLine(metadata);
      _metadataTree.SelectedMetadataChanged += showDoc;
      
      try
      {
        def path = SettingsPath();
        def settings = Settings(path);
        foreach (path in settings.LoadedAssemblyPaths)
          _metadataTree.OpenAssemblyFromFile(path);
          
        _metadataTree.CurrentSelectionPath = settings.CurrentSelectionPath;
      }
      catch { | _ => () }
    }
    
    BasePath : string
    {
      [Memoize] get { Path.GetDirectoryName(Uri(Reflection.Assembly.GetExecutingAssembly().Location).LocalPath) }
    }
    
    [Memoize]
    SettingsPath() : string
    {
      Uri(Reflection.Assembly.GetExecutingAssembly().Location).LocalPath + ".settings"
    }
    
    _fileOpenMenu_Click(_ : object,  _ : System.EventArgs) : void
    {
      when (OpenAssembly() is Some(assemblyPath))
        _metadataTree.OpenAssemblyFromFile(assemblyPath);
    }

    OpenAssembly() : option[string]
    {
      def path1 = Environment.GetEnvironmentVariable("Nemerle");
        def path2 = path1 ?? Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles"), "Nemerle");

      _openFileDialog.InitialDirectory = path2;
      
      if (_openFileDialog.ShowDialog(this) == DialogResult.OK)
        Some(_openFileDialog.FileName)
      else
        None()
    }
  
    private showDoc(metadata : Metadata) : void
    {
      def showTypeInfo(type : ITypeInfo) : XElement
      {
        match (_host.Docs.GetDoc(type))
        {
          | Some(elem) => elem
          | _          => xml <#<p>no docs</>#>
        }
      }
      //_docLabel.Text =
      def htmlBody = 
        match (metadata)
        {
          | MacroInfo(m)   => _host.MacroInfoToHtml(m)
          | TypeInfo(type) => showTypeInfo(type)
          | _              => xml <# <p>docs is not suported for this node</>#>;
        };
        
      def cssPath = $@"file:///$BasePath\article.css";
        
      def htnl2 = xml <# 
<html>
  <head>
    <title>...</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <link rel="stylesheet"  type="text/css" href=$cssPath />
  </head>
  <body>
    $htmlBody
  </body>
</html> #>;  
        
      File.WriteAllText(TempPath, htnl2.ToString());
      _webBrowser.Navigate(TempPath);
    }

    private MainForm_FormClosed(_ : object,  _e : System.Windows.Forms.FormClosedEventArgs) : void
    {
      def config = Settings(_metadataTree.LoadedAssemblyPaths, _metadataTree.CurrentSelectionPath);
      def xmlDoc = config.ToXml();
      xmlDoc.Save(SettingsPath(), SaveOptions.OmitDuplicateNamespaces);
    }
  }
}
